package io.jnet.client;

import java.nio.channels.AsynchronousChannelGroup;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import com.jfireframework.baseutil.exception.JustThrowException;
import io.jnet.client.api.AioClient;
import io.jnet.client.api.ClientChannelContextBuilder;
import io.jnet.client.api.ClientListener;
import io.jnet.client.util.DefaultClientListener;

public class AioClientBuilder
{
    public static enum ExecutorMode
    {
        FIX, CACHED
    }
    
    // 服务器的启动端口
    private int                         port         = -1;
    /**
     * 处理socket事件的起始线程数。如果线程池模式选择固定线程数模式的话，则这个数值就是线程数的值。如果线程池模式选择cache模式的话，则这个数值是初始线程数。
     */
    private int                         ioThreadNum  = Runtime.getRuntime().availableProcessors();
    private ExecutorMode                executorMode = ExecutorMode.FIX;
    private String                      serverIp     = "0.0.0.0";
    private ThreadFactory               threadFactory;
    private AsynchronousChannelGroup    channelGroup;
    private ClientListener              clientListener;
    private ClientChannelContextBuilder clientChannelContextBuilder;
    
    public AioClient build()
    {
        try
        {
            if (threadFactory == null)
            {
                threadFactory = new ThreadFactory() {
                    int i = 1;
                    
                    @Override
                    public Thread newThread(Runnable r)
                    {
                        return new Thread(r, "客户端IO线程-" + (i++));
                    }
                };
            }
            if (channelGroup == null)
            {
                switch (executorMode)
                {
                    case FIX:
                        channelGroup = AsynchronousChannelGroup.withFixedThreadPool(ioThreadNum, threadFactory);
                        break;
                    case CACHED:
                        channelGroup = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(threadFactory), ioThreadNum);
                        break;
                }
            }
            if (clientListener == null)
            {
                clientListener = new DefaultClientListener();
            }
            return new BufferAioClient(clientChannelContextBuilder, channelGroup, serverIp, port, clientListener);
        }
        catch (Throwable e)
        {
            throw new JustThrowException(e);
        }
    }

    public void setPort(int port)
    {
        this.port = port;
    }

    public void setIoThreadNum(int ioThreadNum)
    {
        this.ioThreadNum = ioThreadNum;
    }

    public void setExecutorMode(ExecutorMode executorMode)
    {
        this.executorMode = executorMode;
    }

    public void setServerIp(String serverIp)
    {
        this.serverIp = serverIp;
    }

    public void setThreadFactory(ThreadFactory threadFactory)
    {
        this.threadFactory = threadFactory;
    }

    public void setChannelGroup(AsynchronousChannelGroup channelGroup)
    {
        this.channelGroup = channelGroup;
    }

    public void setClientListener(ClientListener clientListener)
    {
        this.clientListener = clientListener;
    }

    public void setClientChannelContextBuilder(ClientChannelContextBuilder clientChannelContextBuilder)
    {
        this.clientChannelContextBuilder = clientChannelContextBuilder;
    }
    
}
